import { ErrorCode } from "../src/config/ErrorCode";
import { GameConfig } from "../src/config/GameConfig";
import { ServerConfig } from "../src/config/ServerConfig";
import DateUtil from "../src/engine/utils/DateUtil";
import { IdentifiUtil } from "../src/engine/utils/IdentifiUtil";
import { Logger } from "../src/engine/utils/Logger";
import { Md5Helper } from "../src/engine/utils/Md5Helper";
import { WebUtil } from "../src/engine/utils/WebUtil";
import { ResponseModel } from "../src/model/ResponseModel";
import { ServerManager } from "../src/server/ServerManager";
import { AccountDao } from "./dao/AccountDao";
import { UserDao } from "./dao/UserDao";
import { AccountEntity } from "./entity/AccountEntity";
import { WechatSdkManager } from "./WechatSdkManager";

const request = require('request');
const crypto = require("crypto");

const routerMap = {
    updateServerStatus: "/updateServerStatus",
    register: "/register",
    account_auth: "/account_auth",
    wechat_auth: "/wechat_auth",
    get_user_data: "/get_user_data"
}

export class AccountReqHandler {

    public static instance: AccountReqHandler = new AccountReqHandler();


    public init(app) {
        for (const key in routerMap) {
            app.use(routerMap[key], this.onBaseRoot.bind(this))
        }
    }

    private onBaseRoot(req, resp) {
        try {
            let ip: string = WebUtil.getIpByExpressReq(req);
            Logger.log("onBaseRoot==", ip, req.baseUrl)
            if (req.baseUrl == routerMap.updateServerStatus) {
                ServerConfig.initConfig(ServerConfig.nowServerConfig.nowPort)
                resp.end("success");
            }
            else if (req.baseUrl == routerMap.register) {
                this.checkBody(ip, req, resp, this.on_register.bind(this))
            }
            else if (req.baseUrl == routerMap.account_auth) {
                this.checkBody(ip, req, resp, this.on_account_auth.bind(this))
            }
            else if (req.baseUrl == routerMap.wechat_auth) {
                this.checkBody(ip, req, resp, this.on_wechat_auth.bind(this))
            }
            else if (req.baseUrl == routerMap.get_user_data) {
                this.checkBody(ip, req, resp, this.on_get_user_data.bind(this))
            }
        } catch (error) {
            Logger.warn("onBaseRoot error", error);
        }
    }

    private checkBody(ip: string, req, resp, callback: Function) {
        if (req.body) {
            try {
                let jsonObj = JSON.parse(req.body);
                let k: string = jsonObj["k"];
                let data: object = jsonObj["data"]
                if (k == Md5Helper.getMd5_encrypt(JSON.stringify(data))) {
                    callback && callback(req, resp, data, ip);
                }
                else {
                    Logger.error("收到非法Http请求 key", ip, req.body)
                    resp.end();
                }
            } catch (error) {
                Logger.error("收到非法Http请求body", ip, req.body, error)
                resp.end();
            }
        }
        else {
            resp.end();
        }
    }

    private async on_register(req, resp, data: object, ip) {
        Logger.log("on_register=", data, ip)
        let account: string = data["account"]
        let password: string = data["password"]
        let channel: number = data["channel"]
        let os: string = data["os"]
        let phone_type: string = data["phone_type"]
        let bundle_name: string = data["bundle_name"]
        let system_version: string = data["system_version"]
        let udid: string = data["udid"]
        if (!IdentifiUtil.isEmojiCharacter(account)) {
            let oldAccount: AccountEntity = await AccountDao.get_account_info(account)
            // Logger.log("on_register===isExist=", isExist)
            if (oldAccount) {
                resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "已存在账号")))
            } else {
                // let isExistIp: boolean = await AccountDao.is_ip_exist(ip)
                let token: string = Md5Helper.createToken(account)
                let accountEntity: AccountEntity = new AccountEntity()
                accountEntity.account = account
                accountEntity.password = password
                accountEntity.account_type = GameConfig.Account_Type.Account
                accountEntity.token = token
                accountEntity.status = GameConfig.Status_Type.Normal
                accountEntity.ip = ip
                accountEntity.nick_name = account
                accountEntity.channel = channel
                accountEntity.os = os
                accountEntity.phone_type = phone_type
                accountEntity.bundle_name = bundle_name
                accountEntity.system_version = system_version
                accountEntity.udid = udid
                accountEntity.sex = GameConfig.Sex_Type.Mail;
                accountEntity.create_time = DateUtil.formatDateStr(DateUtil.now())
                accountEntity = await AccountDao.update_account(accountEntity)
                if (accountEntity) {
                    let data: object = {
                        "account": account,
                        "token": token,
                        "nickname": account,
                        "sex": accountEntity.sex,
                        "headimgurl": accountEntity.headimgurl,
                        "account_type": accountEntity.account_type,
                        "server": await this.getHallServer(account)
                    }
                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Suc, "", data)))

                } else {
                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "数据库错误，创建账号失败")))
                }
            }
        } else {
            resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "账号包含非法字符")))
        }


    }

    private async on_account_auth(req, resp, data: object, ip) {
        // Logger.log("on_account_auth=", data, ip)
        let account: string = data["account"]
        let password: string = data["password"]
        let channel: number = data["channel"]
        let os: string = data["os"]
        let phone_type: string = data["phone_type"]
        let bundle_name: string = data["bundle_name"]
        let system_version: string = data["system_version"]
        let udid: string = data["udid"]

        let accountResult: AccountEntity = await AccountDao.get_account_info(account)
        if (accountResult) {
            if (password == accountResult.password) {
                if (accountResult.status == GameConfig.Status_Type.FengJin) {
                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, "用户被冻结")))
                } else {
                    let token: string = Md5Helper.createToken(account)
                    accountResult.ip = ip
                    accountResult.channel = channel
                    accountResult.os = os
                    accountResult.phone_type = phone_type
                    accountResult.bundle_name = bundle_name
                    accountResult.system_version = system_version
                    accountResult.udid = udid
                    accountResult.token = token
                    accountResult.last_login_time = DateUtil.formatDateStr(DateUtil.now())
                    accountResult = await AccountDao.update_account(accountResult);
                    if (accountResult) {
                        let respData: object = {
                            "account": account,
                            "token": token,
                            "nickname": accountResult.nick_name,
                            "sex": accountResult.sex,
                            "headimgurl": accountResult.headimgurl,
                            "account_type": GameConfig.Account_Type.Account,
                            "server": await this.getHallServer(account)
                        }
                        resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Suc, "", respData)))
                    }
                    else {
                        resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Db_Error, "数据库错误")))
                    }
                }
            } else {
                Logger.log("on_account_auth账号密码不对", password, accountResult["password"])
                resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.LoginError_NoPass, "登录密码错误")))
            }
        } else {
            resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.LoginError_NoUser, "不存在该用户")))
        }
    }

    private async on_wechat_auth(req, resp, data: object, ip) {
        Logger.log("on_wechat_auth=", data, ip)
        let code: string = data["code"]
        let channel: number = data["channel"]
        let os: string = data["os"]
        let phone_type: string = data["phone_type"]
        let bundle_name: string = data["bundle_name"]
        let system_version: string = data["system_version"]
        let udid: string = data["udid"]

        WechatSdkManager.instance.get_access_token(code, (respData) => {
            if (respData.status == 200) {
                Logger.log("get_access_token===resp=", respData.data)
                if (respData.data["errcode"] && respData.data["errmsg"]) {
                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, respData.data["errmsg"])))
                } else {
                    let openid: string = respData.data["openid"]
                    let access_token: string = respData.data["access_token"]
                    WechatSdkManager.instance.get_userinfo(access_token, openid, async (respData) => {
                        if (respData.status == 200) {
                            Logger.log("get_userinfo===resp=", respData.data)
                            if (respData.data["errcode"] && respData.data["errmsg"]) {
                                resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, respData.data["errmsg"])))
                            }
                            else {
                                // let unionid: string = respData.data["openid"]
                                let unionid: string = respData.data["unionid"]
                                let openid: string = respData.data["openid"]
                                let nickname: string = respData.data["nickname"]
                                let sex: number = respData.data["sex"]
                                let headimgurl: string = respData.data["headimgurl"]
                                let token: string = Md5Helper.createToken(unionid)
                                let accountEntity: AccountEntity = await AccountDao.get_account_info(unionid)
                                if (accountEntity) {
                                } else {
                                    accountEntity = new AccountEntity()
                                    accountEntity.password = "123456"
                                    accountEntity.account_type = GameConfig.Account_Type.Wechat
                                }
                                accountEntity.sex = sex
                                accountEntity.nick_name = nickname
                                accountEntity.headimgurl = headimgurl
                                accountEntity.token = token
                                accountEntity.ip = ip
                                accountEntity.channel = channel
                                accountEntity.os = os
                                accountEntity.phone_type = phone_type
                                accountEntity.bundle_name = bundle_name
                                accountEntity.system_version = system_version
                                accountEntity.udid = udid
                                accountEntity = await AccountDao.update_account(accountEntity)
                                if (accountEntity) {
                                    let data: object = {
                                        "account": accountEntity.account,
                                        "token": accountEntity.token,
                                        "nickname": accountEntity.nick_name,
                                        "sex": accountEntity.sex,
                                        "headimgurl": accountEntity.headimgurl,
                                        "account_type": accountEntity.account_type,
                                    }
                                    data["server"] = await this.getHallServer(unionid)
                                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Suc, "", data)))
                                } else {
                                    resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Db_Error, "数据库错误,创建账号失败")))
                                }
                            }

                        } else {
                            resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, respData.statusText)))
                        }
                    })
                }
            } else {
                Logger.log("get_access_token===resp==error=", respData.statusText)
                resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Fail, respData.statusText)))
            }
        })
    }

    private async getHallServer(account: string) {
        // let resultServerConfig: ServerConfig = await ServerManager.instance.is_in_server(account)
        // if (!resultServerConfig) {
        // resultServerConfig = ServerConfig.randomHallServer()
        // }
        // return resultServerConfig;

        return ServerConfig.randomHallServer()
    }


    private async on_get_user_data(req, resp, data: object, ip) {
        let userid: number = data["userid"]
        let userData: object = await UserDao.get_user_data_by_userid(userid)
        resp.end(JSON.stringify(ResponseModel.create(ErrorCode.Code.Suc, "", userData)))
    }



}